﻿using System;
using System.Drawing;
using System.Collections.Generic;
using Noris.Schedule.Support.Core;

namespace Noris.Schedule.Support.Services
{
	#region CLASS DataSourceRequest : BÁZOVÁ TŘÍDA. Jeden požadavek na datový zdroj. Umožní získávat data i asynchronně.
	/// <summary>
	/// DataSourceRequest : jeden požadavek na datový zdroj. Umožní získávat data asynchronně.
	/// Pracuje ve spojení s třídou Aps.Core.WorkQueueCls, jejímž je generikem.
	/// Každá jedna instance této třídy DataSourceRequest představuje jeden požadavek na data, který je možno vyřídit synchronně / asynchronně.
	/// Součástí dat této třídy je: priorita požadavku, identifikace požadavku, vstupní data (požadavek), výstupní data (výsledek).
	/// Součástí priority je i řešení aktivity požadavků: některé požadavky přísluší aktivní stránce, ty by měly být vyřizovány přednostně.
	/// Požadavky neaktivní stránky budou řešeny až poté.
	/// </summary>
	public class DataSourceRequest : ICallBackTarget, IComparable
	{
		#region KONSTRUKTOR
		/// <summary>
		/// Chráněný konstruktor
		/// </summary>
		/// <param name="graphID">ID grafu, jednoznačný klíč v rámci tabule (to je klíčem pro rozpoznání cíle odpovědí)</param>
		/// <param name="graphDeclaration">Deklarace grafu, nese v sobě další informace o grafu</param>
		/// <param name="requestType">Typ požadavku</param>
		/// <param name="priority">Aktuální priorita</param>
		protected DataSourceRequest(int graphID, GraphDeclarationItemCls graphDeclaration, DataSourceRequestType requestType, int priority)
		{
			this.RequestID = ++LastRequestId;
			this.GraphID = graphID;
			this.GraphDeclaration = graphDeclaration;
			this.RequestType = requestType;
			this.Priority = priority;
			this.DataVersion = Steward.CurrentDataVersion;
		}
		/// <summary>
		/// Vizualizace
		/// </summary>
		/// <returns></returns>
		public override string ToString()
		{
			return "{" + this.RequestType.ToString() + " (ID=" + this.RequestID.ToString() + ")}";
		}
		#endregion
		#region BÁZOVÉ PROPERTY
		/// <summary>
		/// Posledně použité číslo ID požadavku
		/// </summary>
		protected static long LastRequestId = 0;
		/// <summary>
		/// { get; } ID požadavku. Každý požadavek má unikátní ID.
		/// </summary>
		public long RequestID { get; protected set; }
		/// <summary>
		/// { get; } Druh požadavku
		/// </summary>
		public DataSourceRequestType RequestType { get; protected set; }
		/// <summary>
		/// { get; } ID grafu, který požadavek vydal
		/// </summary>
		public int GraphID { get; protected set; }
		/// <summary>
		/// Deklarace grafu, tak jak byla připravena v deklarátoru
		/// </summary>
		public GraphDeclarationItemCls GraphDeclaration { get; protected set; }
		/// <summary>
		/// { get; } Typ grafu, který je zdrojem dotazu.
		/// Je načten z this.GraphDeclaration.DefaultGraphMode
		/// </summary>
		public RowGraphMode DefaultGraphMode { get { return (this.GraphDeclaration == null ? RowGraphMode.NoDrawingElements : this.GraphDeclaration.DefaultGraphMode); } }
		/// <summary> { get; }
		/// { get; } Přidaná informace o grafu, který je zdrojem dotazu.
		/// Je načten z this.GraphDeclaration.Tag
		/// </summary>
		public object Tag { get { return (this.GraphDeclaration == null ? null : this.GraphDeclaration.Tag); } }
		/// <summary>
		/// { get; set; } Priorita požadavku. Nižší hodnoty = vyšší priorita.
		/// </summary>
		public int Priority { get; set; }
		/// <summary>
		/// { get; } Verze dat, která se v tomto požadavku zpracovává.
		/// Grafická tabule sem vkládá verzi dat, která je aktuálně vybraná v Toolbaru.
		/// Typ objektu = ten typ, který datový zdroj vrací z requestu DataSourceRequestType.QueryDataVersion,
		/// v objektech v seznamu request.QueryResultDataVersionList, v property Tag objektů StringTag.
		/// </summary>
		public object DataVersion { get; protected set; }
		/// <summary>
		/// { get; } Příznak, zda tento požadavek vydal aktivní graf (na začátku vždy, po změně aktivního grafu se znovu vyhodnotí).
		/// true = požadavek aktivního grafu / false = požadavek neaktivního grafu.
		/// Hodnotu nastavuje metoda this.SetActiveGraph(int activeGraph).
		/// </summary>
		public bool GraphIsActive { get; protected set; }
		/// <summary>
		/// { get; } GID pro identifikaci dočasného elementu.
		/// Tento údaj slouží pro grafickou vrstvu, která při asynchronním požadavku založí Temp element na plochu, 
		/// a po dokončení tohoto požadavku tento Temp element odebere.
		/// </summary>
		public GID TempGId { get { return new GID(0, (int)(RequestID & Int32.MaxValue)); } }
		/// <summary>
		/// { get; } Metoda, která je volána při postupu v průběhu zpracování požadavku.
		/// </summary>
		public CallbackTargetDelegate ProgressMethod { get; protected set; }
		/// <summary>
		/// Exception, vyvolaná v průběhu zpracování tohoto požadavku
		/// </summary>
		public Exception ResultException;
		#endregion
		#region AKTIVACE GRAFU = PŘEHODNOCENÍ AKTIVITY POŽADAVKU
		/// <summary>
		/// Metoda jednoduše nastaví příznak aktivity tohoto požadavku podle aktivity grafu.
		/// Pokud je graf, který vydal tento požadavek, grafem aktivním (předané ID grafu), pak je i jeho požadavek aktivní,
		/// a má vyšší prioritu. Požadavky neaktivních grafů mají prioritu nízkou.
		/// </summary>
		/// <param name="activeGraphId">ID nyní aktivního grafu</param>
		public void SetActiveGraph(int activeGraphId)
		{
			this.GraphIsActive = (this.GraphID == activeGraphId);
		}
		#endregion
		#region GENERICKÉ PŘETYPOVÁNÍ NA KONKRÉTNÍHO POTOMKA
		/// <summary>
		/// Metoda vrátí vstupující request přetypovaný na požadovaného potomka (pokud to lze přetypovat).
		/// Případné chyby hlásí.
		/// </summary>
		/// <typeparam name="R"></typeparam>
		/// <param name="requestInput"></param>
		/// <returns></returns>
		public static R TryGetTypedRequest<R>(DataSourceRequest requestInput) where R : DataSourceRequest
		{
			if (requestInput == null)
				Throw.SysError(MessageInfo.Get("Pro zpracování byl předán požadavek, který je null."));

			R request = requestInput as R;
			if (request == null)
				Throw.SysError(MessageInfo.Get("Pro zpracování byl předán požadavek chybného typu. Očekávaný typ je %0, předán byl typ %1.", typeof(R).Name, requestInput.GetType().Name));

			return request;
		}
		#endregion
		#region CALLBACK PROGRESS = VSTUPNÍ BOD VYVOLÁNÍ METODY PROGRGRESU
		///// <summary>
		///// Metoda vyvolá změnu v okně progresu. Předá do ní informace (poměr dokončení, text).
		///// </summary>
		///// <param name="sender">Odesilatel akce = ten, kdo volá (typicky this)</param>
		///// <param name="progressRatio">Poměrná čst, která už je hotová (hodnota 0 až 1, včetně, odpovídá 0% - 100%)</param>
		//public void CallProgress(object sender, float progressRatio)
		//{
		//    if (this.ProgressMethod == null) return;
		//    this.ProgressMethod(sender, new CallbackArgs(CallbackState.RunningLoop, progressRatio));
		//}
		///// <summary>
		///// Metoda vyvolá změnu v okně progresu. Předá do ní informace (poměr dokončení, text).
		///// </summary>
		///// <param name="sender">Odesilatel akce = ten, kdo volá (typicky this)</param>
		///// <param name="text">Text do okna postupu</param>
		//public void CallProgress(object sender, string text)
		//{
		//    if (this.ProgressMethod == null) return;
		//    this.ProgressMethod(sender, new CallbackArgs(CallbackState.RunningLoop, text));
		//}
		///// <summary>
		///// Metoda vyvolá změnu v okně progresu. Předá do ní informace (poměr dokončení, text).
		///// </summary>
		///// <param name="sender">Odesilatel akce = ten, kdo volá (typicky this)</param>
		///// <param name="progressRatio">Poměrná čst, která už je hotová (hodnota 0 až 1, včetně, odpovídá 0% - 100%)</param>
		///// <param name="text">Text do okna postupu</param>
		//public void CallProgress(object sender, float progressRatio, string text)
		//{
		//    if (this.ProgressMethod == null) return;
		//    this.ProgressMethod(sender, new CallbackArgs(CallbackState.RunningLoop, progressRatio, text));
		//}
		#endregion
		#region KOMPARÁTOR = VYHODNOTÍ PRIORITNÍ POŽADAVKY
		/// <summary>
		/// Komparátor: tímto komparátorem se třídí záznamy požadavků, a vybírá se tak první požadavek, který se bude zpracovávat.
		/// Komparátor vrátí -1, pokud (this) je důležitější = zpracuje se dřív než (other);
		/// vrátí +1 pokud (this) je méně důležitý = zpracuje se později než (other);
		/// vrátí 0 pokud jsou si rovny (nemělo by nastávat, pak se třídí náhodně);
		/// </summary>
		/// <param name="obj"></param>
		/// <returns></returns>
		public int CompareTo(object obj)
		{
			if (!(obj is DataSourceRequest)) return 0;
			DataSourceRequest other = obj as DataSourceRequest;
			if (obj == null) return 0;

			// Pokud jsou požadavky z různě aktivních grafů, vyhodnotíme to jako první hledisko:
			if (this.GraphIsActive != other.GraphIsActive)
			{
				if (this.GraphIsActive) return -1;         // Tento je aktivní (druhý je neaktivní): vracím -1 = this je dříve
				if (other.GraphIsActive) return +1;        // Druhý je aktivní (tento je neaktivní): vracím +1 = this je později
			}

			// Stejně aktivní grafy: priorita, a jejich stáří:
			if (this.Priority != other.Priority)
				return this.Priority.CompareTo(other.Priority);    // Nižší priorita bude dříve
			return other.RequestID.CompareTo(this.RequestID);      // U stejné priority budou dříve NOVĚJŠÍ požadavky (abychom při pohybu reagovali na to nejnovější)
		}
		#endregion
		#region ICallBackTarget Members : metody, které předávají informace o pokroku výkonného procesu zpět do volajícího procesu
		/// <summary>
		/// Metoda, která je volána při standardním postupu prací
		/// </summary>
		/// <param name="sender">Odesílatel</param>
		/// <param name="args">Data o průběhu</param>
		void ICallBackTarget.CallTarget(object sender, CallBackTargetArgs args)
		{
			if (this.ProgressMethod == null) return;
			this.ProgressMethod(sender, new CallbackArgs(CallbackState.RunningLoop, (float)args.Ratio, args.TextLines));
		}
		#endregion
	}
	#endregion
	#region CLASS DataSourceRequestReadRows : požadavek na načtení dat řádků grafu
	/// <summary>
	/// DataSourceRequestReadRows : požadavek na načtení dat řádků grafu
	/// </summary>
	public class DataSourceRequestReadRows : DataSourceRequest
	{
		#region KONSTRUKCE
		/// <summary>
		/// Protected konstruktor. Objekt má být vytvořen statickým konstruktorem.
		/// </summary>
		/// <param name="graphID">ID grafu, který požadavek vydal</param>
		/// <param name="graphDeclaration">Deklarace grafu, který požadavek vydal. Vstupuje do Requestu a nese informace do datového zdroje.</param>
		/// <param name="requestType">Typ požadavku</param>
		/// <param name="priority">Priorita požadavku</param>
		protected DataSourceRequestReadRows(int graphID, GraphDeclarationItemCls graphDeclaration, DataSourceRequestType requestType, int priority) :
			base(graphID, graphDeclaration, requestType, priority)
		{ }
		/// <summary>
		/// Vytvoří a vrátí request pro načítání záznamů TopLevelRead.
		/// </summary>
		/// <param name="graphID">ID grafu, který požadavek vydal</param>
		/// <param name="graphDeclaration">Deklarace grafu, který požadavek vydal. Vstupuje do Requestu a nese informace do datového zdroje.</param>
		/// <param name="rowGId">GID, který určuje třídu záznamů k načítání. Pokud je předán GID s hodnotou AllRecords = true, vracíme všechny záznamy dané třídy.</param>
		/// <param name="graphType">Požadovaný typ grafu. Pokud bude datovým zdrojem akceptován, bude vložen do jednotlivých vygenerovaných řádků. 
		/// Pokud nebude akceptovatelný, bude vložen přiměřený jiný. 
		/// Vykreslování řádku grafu probíhá podle hodnoty, která je uložena v konkrétním řádku.</param>
		/// <returns>Request, který zajistí načítání těchto dat</returns>
		public static DataSourceRequestReadRows CreateTopLevelRead(int graphID, GraphDeclarationItemCls graphDeclaration, GID rowGId, RowGraphMode graphType)
		{
			DataSourceRequestReadRows request = new DataSourceRequestReadRows(graphID, graphDeclaration, DataSourceRequestType.TopLevelRead, 5);
			request.RequestRowGId = rowGId;
			request.RequestedGraphMode = graphType;
			return request;
		}
		/// <summary>
		/// Vytvoří a vrátí request pro načítání záznamů SubRowsRead.
		/// </summary>
		/// <param name="graphID">ID grafu, který požadavek vydal</param>
		/// <param name="graphDeclaration">Deklarace grafu, který požadavek vydal. Vstupuje do Requestu a nese informace do datového zdroje.</param>
		/// <param name="rowGId">GID záznamu, jehož podřízené prvky hledám. Pokud je předán GID s hodnotou AllRecords = true, vracíme všechny záznamy dané třídy.</param>
		/// <param name="graphType">Požadovaný typ grafu. Pokud bude datovým zdrojem akceptován, bude vložen do jednotlivých vygenerovaných řádků. 
		/// Pokud nebude akceptovatelný, bude vložen přiměřený jiný. 
		/// Vykreslování řádku grafu probíhá podle hodnoty, která je uložena v konkrétním řádku.</param>
		/// <returns>Request, který zajistí načítání těchto dat</returns>
		public static DataSourceRequestReadRows CreateSubRowsRead(int graphID, GraphDeclarationItemCls graphDeclaration, GID rowGId, RowGraphMode graphType)
		{
			DataSourceRequestReadRows request = new DataSourceRequestReadRows(graphID, graphDeclaration, DataSourceRequestType.SubRowsRead, 5);
			request.RequestRowGId = rowGId;
			request.RequestedGraphMode = graphType;
			return request;
		}
		#endregion
		#region PROPERTY
		/// <summary>
		/// { get; } Požadovaný GID řádku. Pro tento řádek požadujeme získat data.
		/// Může jít o GID typu AllRecords (jeho číslo záznamu je 0), anebo konkrétní řádek.
		/// </summary>
		public GID RequestRowGId { get; protected set; }
		/// <summary>
		/// { get; } Typ grafu. Pro tento typ grafu máme načítat data. 
		/// Pokud datová třída nepodporuje tento typ grafu, načte data tak, jak umí.
		/// Skutečný typ grafu se ukládá do položek výstupního seznamu.
		/// </summary>
		public RowGraphMode RequestedGraphMode { get; protected set; }
		/// <summary>
		/// { get; set; } Výsledek: soupis řádků.
		/// </summary>
		public List<IDataRow> ResultItems
		{
			get
			{
				if (_ResultItems == null)
					_ResultItems = new List<IDataRow>();
				return _ResultItems;
			}
			set { _ResultItems = value; }
		}
		private List<IDataRow> _ResultItems;
		#endregion
	}
	#endregion
	#region CLASS DataSourceRequestReadElements : požadavek na načtení elementů daného řádků / explicitního seznamu elementů
	/// <summary>
	/// DataSourceRequestReadElements : požadavek na načtení elementů daného řádků / explicitního seznamu elementů
	/// </summary>
	public class DataSourceRequestReadElements : DataSourceRequest
	{
		#region KONSTRUKCE
		/// <summary>
		/// Protected konstruktor. Objekt má být vytvořen statickým konstruktorem.
		/// </summary>
		/// <param name="graphID">ID grafu, který požadavek vydal</param>
		/// <param name="graphDeclaration">Deklarace grafu, který požadavek vydal. Vstupuje do Requestu a nese informace do datového zdroje.</param>
		/// <param name="requestType">Typ požadavku</param>
		/// <param name="priority">Priorita požadavku</param>
		protected DataSourceRequestReadElements(int graphID, GraphDeclarationItemCls graphDeclaration, DataSourceRequestType requestType, int priority) :
			base(graphID, graphDeclaration, requestType, priority)
		{ }
		/// <summary>
		/// Vytvoří a vrátí request pro načítání záznamů ElementsRead.
		/// </summary>
		/// <param name="graphID">ID grafu, který požadavek vydal</param>
		/// <param name="graphDeclaration">Deklarace grafu, který požadavek vydal. Vstupuje do Requestu a nese informace do datového zdroje.</param>
		/// <param name="rowGId">GID záznamu, jehož prvky grafu hledám.</param>
		/// <param name="graphType">Typ grafu, pro který se generují elementy</param>
		/// <param name="timeRange">Časový rozsah, pro který hledám data</param>
		/// <param name="workGId">WorkGID, task jehož elementy chci načítat. Využívá se ve spojení s loadAllElement = true.</param>
		/// <param name="loadAllElement">Požadavek na načtení všech elementů.</param>
		/// <returns>Request, který zajistí načítání těchto dat</returns>
		public static DataSourceRequestReadElements CreateElementsForRowRead(int graphID, GraphDeclarationItemCls graphDeclaration, GID rowGId, RowGraphMode graphType, TimeRange timeRange, GID workGId, bool loadAllElement)
		{
			DataSourceRequestReadElements request = new DataSourceRequestReadElements(graphID, graphDeclaration, DataSourceRequestType.ElementsRead, 5);
			request.RequestRowGId = rowGId;
			request.RequestedGraphMode = graphType;
			request.RequestedTimeRange = timeRange;
			request.RequestedWorkGId = workGId;
			request.RequestedLoadAllElements = loadAllElement;
			return request;
		}
		/// <summary>
		/// Vytvoří a vrátí request pro načtení exaktně specifikovaných elementů (soupis pointerů na elementy).
		/// </summary>
		/// <param name="graphID">ID grafu, který požadavek vydal</param>
		/// <param name="graphDeclaration">Deklarace grafu, který požadavek vydal. Vstupuje do Requestu a nese informace do datového zdroje.</param>
		/// <param name="elementsMap">Soupis elementů, které je třeba načíst</param>
		/// <param name="graphType">Typ grafu, pro který se hledají vztahy</param>
		/// <returns></returns>
		public static DataSourceRequestReadElements CreateMissingElementsRead(int graphID, GraphDeclarationItemCls graphDeclaration, List<DataPointerStr> elementsMap, RowGraphMode graphType)
		{
			DataSourceRequestReadElements request = new DataSourceRequestReadElements(graphID, graphDeclaration, DataSourceRequestType.ElementsMapRead, 5);
			request.RequestElementsMap = elementsMap;
			request.RequestedGraphMode = graphType;
			return request;
		}
		#endregion
		#region PROPERTY
		/// <summary>
		/// { get; } Požadovaný GID řádku. Pro tento řádek požadujeme získat data.
		/// Může jít o GID typu AllRecords (jeho číslo záznamu je 0), anebo konkrétní řádek.
		/// </summary>
		public GID RequestRowGId { get; protected set; }
		/// <summary>
		/// { get; } Typ grafu. Pro tento typ grafu máme načítat data. 
		/// Pokud datová třída nepodporuje tento typ grafu, načte data tak, jak umí.
		/// Skutečný typ grafu se ukládá do položek výstupního seznamu.
		/// </summary>
		public RowGraphMode RequestedGraphMode { get; protected set; }
		/// <summary>
		/// { get; } Rozšířený požadavek, načítat pouze elementy týkající se daného WorkGIDu (typicky jde o task).
		/// Načítají se pak elementy pouze pro daný GID (řádek), týkající se jednoho WorkGIDu, s ignorováním dalších WorkGID.
		/// </summary>
		public GID RequestedWorkGId { get; protected set; }
		/// <summary>
		/// { get; } Požadovaný časový úsek pro načítání dat elementů.
		/// </summary>
		public TimeRange RequestedTimeRange { get; protected set; }
		/// <summary>
		/// { get; } Požadavek na načtení všech elementů.
		/// </summary>
		public bool RequestedLoadAllElements { get; protected set; }
		/// <summary>
		/// { get; } Seznam pointerů na elementy, které je třeba načíst.
		/// Načtené elementy se mají uložit do this.ResultElements
		/// </summary>
		public List<DataPointerStr> RequestElementsMap { get; protected set; }
		/// <summary>
		/// { get; set; } Výsledek: soupis elementů.
		/// </summary>
		public List<IDataElement> ResultElements
		{
			get
			{
				if (_ResultElements == null)
					_ResultElements = new List<IDataElement>();
				return _ResultElements;
			}
			set { _ResultElements = value; }
		}
		private List<IDataElement> _ResultElements;
		/// <summary>
		/// { get; set; } Výsledek: byly nahrány všechny elementy.
		/// </summary>
		public bool ResultLoadAllElements { get; set; }
		#endregion
	}
	#endregion
	#region CLASS DataSourceRequestReadRelations : požadavek na načtení vztahů mezi elementy (jak Relations, tak Link)
	/// <summary>
	/// DataSourceRequestReadRelations : požadavek na načtení vztahů mezi elementy.
	/// Slouží pro načítání vztahů jak Relations (vztahy mezi závislými elementy, pro konkrétní element(y) = request DataSourceRequestType.CreateDataRelationNet,
	/// tak i pro načítání Linků mezi elementy (trvale vykreslované spojení elementů) = request DataSourceRequestType.CreateDataLinkNet.
	/// </summary>
	public class DataSourceRequestReadRelations : DataSourceRequest
	{
		#region KONSTRUKCE
		/// <summary>
		/// Protected konstruktor. Objekt má být vytvořen statickým konstruktorem.
		/// </summary>
		/// <param name="graphID">ID grafu, který požadavek vydal</param>
		/// <param name="graphDeclaration">Deklarace grafu, který požadavek vydal. Vstupuje do Requestu a nese informace do datového zdroje.</param>
		/// <param name="requestType">Typ požadavku</param>
		/// <param name="priority">Priorita požadavku</param>
		protected DataSourceRequestReadRelations(int graphID, GraphDeclarationItemCls graphDeclaration, DataSourceRequestType requestType, int priority) :
			base(graphID, graphDeclaration, requestType, priority)
		{ }
		/// <summary>
		/// Vytvoří a vrátí request pro načtení sítě vztahů pro daný GID (DataSourceRequestType.CreateDataRelationNet).
		/// </summary>
		/// <param name="graphID">ID grafu, který požadavek vydal</param>
		/// <param name="graphDeclaration">Deklarace grafu, který požadavek vydal. Vstupuje do Requestu a nese informace do datového zdroje.</param>
		/// <param name="elementPointer">Požadovaný pointer na element. Pro tento element požadujeme získat data.</param>
		/// <param name="graphType">Typ grafu, pro který se hledají vztahy</param>
		/// <returns></returns>
		public static DataSourceRequestReadRelations CreateRelationsNet(int graphID, GraphDeclarationItemCls graphDeclaration, DataPointerStr elementPointer, RequestRelationLevel relationLevel, RowGraphMode graphType)
		{
			DataSourceRequestReadRelations request = new DataSourceRequestReadRelations(graphID, graphDeclaration, DataSourceRequestType.CreateDataRelationNet, 5);
			request.RequestElementPointer = elementPointer;
            request.RequestRelationLevel = relationLevel;
			request.RequestedGraphMode = graphType;
			return request;
		}
		/// <summary>
		/// Vytvoří a vrátí request pro načtení sítě linků pro všechny elementy tohoto grafu (DataSourceRequestType.CreateDataLinkNet).
		/// </summary>
		/// <param name="graphID">ID grafu, který požadavek vydal</param>
		/// <param name="graphDeclaration">Deklarace grafu, který požadavek vydal. Vstupuje do Requestu a nese informace do datového zdroje.</param>
		/// <param name="graphType">Typ grafu, pro který se hledají vztahy</param>
		/// <returns></returns>
		public static DataSourceRequestReadRelations CreateLinkNet(int graphID, GraphDeclarationItemCls graphDeclaration, RowGraphMode graphType)
		{
			DataSourceRequestReadRelations request = new DataSourceRequestReadRelations(graphID, graphDeclaration, DataSourceRequestType.CreateDataLinkNet, 5);
			request.RequestElementPointer = DataPointerStr.Empty;
            request.RequestRelationLevel = RequestRelationLevel.None;
			request.RequestedGraphMode = graphType;
			return request;
		}
		#endregion
		#region PROPERTY
		/// <summary>
		/// { get; } Požadovaný pointer na element. Pro tento element požadujeme získat data.
		/// Je naplněn při požadavku typu CreateDataRelationNet = čtení vztahů jednoho elementu.
		/// V požadavku DataSourceRequestType.CreateDataLinkNet je Empty.
		/// </summary>
		public DataPointerStr RequestElementPointer { get; protected set; }
        /// <summary>
        /// Požadovaná úroveň načítaných vztahů
        /// </summary>
        public RequestRelationLevel RequestRelationLevel { get; protected set; }
		/// <summary>
		/// { get; } Typ grafu. Pro tento typ grafu máme načítat data. 
		/// Pokud datová třída nepodporuje tento typ grafu, načte data tak, jak umí.
		/// Skutečný typ grafu se ukládá do položek výstupního seznamu.
		/// </summary>
		public RowGraphMode RequestedGraphMode { get; protected set; }
		/// <summary>
		/// { get; set; } Výsledek: soupis vztahů elementů. 
		/// Ve výchozím stavu je null. 
		/// Pokud datový zdroj neumí najít vztahy, null zde zůstane.
		/// Pokud datový zdroj hledá vztahy, je zde umístěn List. Pokud se nenajde žádný vztah, je seznam prázdný.
		/// </summary>
		public List<DataRelation> ResultRelations { get; set; }
		#endregion
	}
    /// <summary>
    /// Úroveň vztahů, které se mají načítat v requestu typu DataSourceRequestReadRelations 
    /// </summary>
    public enum RequestRelationLevel
    {
        /// <summary>
        /// Žádné vztahy
        /// </summary>
        None = 0,
        /// <summary>
        /// Standardní vztahy (po jednom kliknutí)
        /// </summary>
        Standard,
        /// <summary>
        /// Rozšířené vztahy (po druhém kliknutí na element, na který se kliklo minule)
        /// </summary>
        Extended
    }
	#endregion
	#region CLASS DataSourceRequestFindInterGraph : požadavek na nalezení mezigrafového vztahu
	/// <summary>
	/// DataSourceRequestFindInterGraph : požadavek na nalezení mezigrafového vztahu
	/// </summary>
	public class DataSourceRequestFindInterGraph : DataSourceRequest
	{
		#region KONSTRUKCE
		/// <summary>
		/// Protected konstruktor. Objekt má být vytvořen statickým konstruktorem.
		/// </summary>
		/// <param name="graphID">ID grafu, který požadavek vydal</param>
		/// <param name="graphDeclaration">Deklarace grafu, který požadavek vydal. Vstupuje do Requestu a nese informace do datového zdroje.</param>
		/// <param name="requestType">Typ požadavku</param>
		/// <param name="priority">Priorita požadavku</param>
		protected DataSourceRequestFindInterGraph(int graphID, GraphDeclarationItemCls graphDeclaration, DataSourceRequestType requestType, int priority) :
			base(graphID, graphDeclaration, requestType, priority)
		{ }
		/// <summary>
		/// Vytvoří a vrátí request typu FindInterGraphTargetData pro myší aktivitu nad elementem (je dán jeho pointer)
		/// </summary>
		/// <param name="graphID">ID grafu, který požadavek vydal</param>
		/// <param name="graphDeclaration">Deklarace grafu, který požadavek vydal. Vstupuje do Requestu a nese informace do datového zdroje.</param>
		/// <param name="sourceGraphMode">Typ grafu ve zdrojovém grafu</param>
		/// <param name="eventType">Druh události</param>
		/// <param name="sourceElement">Vstupní element</param>
		/// <returns>Request, který zajistí načítání těchto dat</returns>
		public static DataSourceRequestFindInterGraph CreateFindInterGraphForPointer(int graphID, GraphDeclarationItemCls graphDeclaration, CurrentGraphCrossActivityMode activityMode, RowGraphMode sourceGraphMode, GraphEventType eventType, IDataRow sourceDataRow, DataPointerStr sourceElement)
		{
			DataSourceRequestFindInterGraph request = new DataSourceRequestFindInterGraph(graphID, graphDeclaration, DataSourceRequestType.FindInterGraphTargetData, 5);
			request.CurrentActivityMode = activityMode;
			request.SourceGraphMode = sourceGraphMode;
			request.EventType = eventType;
			request.SourceDataRow = sourceDataRow;
			request.SourceElement = sourceElement;
			return request;
		}
		/// <summary>
		/// Vytvoří a vrátí request typu FindInterGraphTargetData pro myší aktivitu nad elementem (je dán jeho pointer)
		/// </summary>
		/// <param name="graphID">ID grafu, který požadavek vydal</param>
		/// <param name="graphDeclaration">Deklarace grafu, který požadavek vydal. Vstupuje do Requestu a nese informace do datového zdroje.</param>
		/// <param name="sourceGraphMode">Typ grafu ve zdrojovém grafu</param>
		/// <param name="eventType">Druh události</param>
		/// <param name="changeMode">Režim změny (druh editace)</param>
		/// <param name="changedRows">Řádky na vstupním grafu, které se mění/změnily</param>
		/// <returns>Request, který zajistí načítání těchto dat</returns>
		public static DataSourceRequestFindInterGraph CreateFindInterGraphForEdit(int graphID, GraphDeclarationItemCls graphDeclaration, CurrentGraphCrossActivityMode activityMode, RowGraphMode sourceGraphMode, GraphEventType eventType, GridEditingChangeMode changeMode, List<GID> changedRows)
		{
			DataSourceRequestFindInterGraph request = new DataSourceRequestFindInterGraph(graphID, graphDeclaration, DataSourceRequestType.FindInterGraphTargetData, 5);
			request.CurrentActivityMode = activityMode;
			request.SourceGraphMode = sourceGraphMode;
			request.EventType = eventType;
			request.SourceChangeMode = changeMode;
			request.SourceChangedRows = changedRows;
			return request;
		}
		#endregion
		#region PROPERTY
		/// <summary>
		/// Režim aktivity = co se má s daty provést poté, kdy událost skončí.
		/// Na vstupu je hodnota, která je načtena z deklarace grafu pro aktuální typ eventu.
		/// Pokud ji kód změní, pak se pro zpracování informací z odpovědi na tento request použije upravená hodnota.
		/// Běžně se nemění.
		/// </summary>
		public CurrentGraphCrossActivityMode CurrentActivityMode { get; set; }
		/// <summary>
		/// Druh události
		/// </summary>
		public GraphEventType EventType { get; protected set; }
		/// <summary>
		/// { get; } Režim změny ve zdrojovém grafu
		/// </summary>
		public GridEditingChangeMode SourceChangeMode { get; protected set; }
		/// <summary>
		/// { get; } Typ grafu, který je zdrojem dotazu.
		/// Je naplněn při požadavku typu FindInterGraphTargetData = Najít cílová data v mezigrafové aktivitě.
		/// </summary>
		public RowGraphMode SourceGraphMode { get; protected set; }
		/// <summary>
		/// { get; } Pointer na element, který je zdrojem dotazu.
		/// Je naplněn při požadavku typu FindInterGraphTargetData = Najít cílová data v mezigrafové aktivitě.
		/// </summary>
		public DataPointerStr SourceElement { get; protected set; }
		/// <summary>
		/// Data řádku, na němž se nachází aktivní element, nebo na který právě ukázal uživatel (v typu eventu RowEnter)
		/// </summary>
		public IDataRow SourceDataRow { get; protected set; }
		/// <summary>
		/// { get; } Řádky ve zdrojovém grafu, kde došlo ke změně
		/// </summary>
		public List<GID> SourceChangedRows { get; protected set; }
		/// <summary>{ get; set; } 
		/// Odpověď: režim změny seznamu řádků v tomto grafu = co chceme udělat s řádky v našem grafu
		/// </summary>
		public RowListChangeMode ResultRowListChange { get; set; }
		/// <summary>{ get; set; } 
		/// Odpověď: soupis řádků, které chceme načíst do seznamu řádků našeho grafu
		/// </summary>
		public List<IDataRow> ResultItems
		{
			get
			{
				if (_ResultItems == null)
					_ResultItems = new List<IDataRow>();
				return _ResultItems;
			}
			set { _ResultItems = value; }
		}
		private List<IDataRow> _ResultItems;
		/// <summary>
		/// Odpověď: GID řádku, který má být aktivován.
		/// Tento GID, pokud není Empty, má přednost před výsledkem dle this.SelectElementList, protože je konkrétní.
		/// </summary>
		public GID ResultActivateRowGId { get; set; }
		/// <summary>
		/// Odpověď: Filtr na řádky v this grafu: 
		/// pokud datový zdroj chce, aby jako reakce na aktivaci řádku v source grafu došlo k vyfiltrování řádků v this grafu,
		/// nechť do této property uloží seznam řádků this grafu, které mají být viditelné.
		/// Pozor, tento filtr lze zrušit buď tak, že příště se v této property vrátí null, anebo ... - ještě nevím :(  David Janáček.
		/// </summary>
		public List<GID> ResultRowFilterList { get; set; }
		/// <summary>
		/// Odpověď: seznam řádků (GID), které se mají v tomto grafu invalidovat = znovu načíst jejich obsah (elementy).
		/// </summary>
		public List<GID> ResultInvalidateRowList { get; set; }
		/// <summary>{ get; set; }
		/// Odpověď: Soupis elementů, které jsou výsledkem hledání cílových dat v mezigrafové aktivitě.
		/// Má být vyplněn jako odpověď na požadavek typu FindInterGraphTargetData = Najít cílová data v mezigrafové aktivitě.
		/// </summary>
		public List<DataPointerStr> ResultSelectElementList { get; set; }
		/// <summary>
		/// Příznak, že důsledkem editace došlo ke změnám v seznamu linkovaných elementů.
		/// Poté by měla vizuální vrstva znovu načíst seznam linků elementů (požadavkem typu DataSourceRequestReadRelations.CreateLinkNet())
		/// a zobrazovat jej z tohoto nově získaného seznamu.
		/// </summary>
		public bool ResultElementLinkListChanged { get; set; }
		#endregion
	}
	#endregion
	#region CLASS DataSourceRequestGetDataVersions : požadavek na získání soupisu datových verzí
	/// <summary>
	/// DataSourceRequestGetDataVersions : požadavek na získání soupisu datových verzí
	/// </summary>
	public class DataSourceRequestGetDataVersions : DataSourceRequest
	{
		#region KONSTRUKCE
		/// <summary>
		/// Protected konstruktor. Objekt má být vytvořen statickým konstruktorem.
		/// </summary>
		/// <param name="graphID">ID grafu, který požadavek vydal</param>
		/// <param name="graphDeclaration">Deklarace grafu, který požadavek vydal. Vstupuje do Requestu a nese informace do datového zdroje.</param>
		/// <param name="requestType">Typ požadavku</param>
		/// <param name="priority">Priorita požadavku</param>
		protected DataSourceRequestGetDataVersions(int graphID, GraphDeclarationItemCls graphDeclaration, DataSourceRequestType requestType, int priority) :
			base(graphID, graphDeclaration, requestType, priority)
		{ }
		/// <summary>
		/// Vytvoří a vrátí request pro předání dotazo do datového zdroje.
		/// Dotazem se tento request ptá datového zdroje na jeho názor na případný následující request.
		/// Konkrétně: čeká nás request na plánovací proces. Nejprve se přeptám datového zdroje, zda jej chce odmítnout, případně jak dlouho mu to bude trvat a jak se bude akce jmenovat.
		/// </summary>
		/// <param name="graphID">ID grafu, který se ptá.</param>
		/// <param name="graphDeclaration">Deklarace grafu, který požadavek vydal. Vstupuje do Requestu a nese informace do datového zdroje.</param>
		public static DataSourceRequestGetDataVersions CreateDataVersionRequest(int graphID, GraphDeclarationItemCls graphDeclaration)
		{
			DataSourceRequestGetDataVersions request = new DataSourceRequestGetDataVersions(graphID, graphDeclaration, DataSourceRequestType.QueryDataVersion, 5);
			return request;
		}
		#endregion
		#region PROPERTY
		/// <summary>
		/// Výsledek requestu QueryDataVersion: seznam verzí dat, které daný datový zdroj obsahuje.
		/// Typicky se sem umísťuje soupis verzí plánu.
		/// Každá verze je uložena v objektu typu StringTag: kde Text je vizuální prezentace, a Tag obsahuje data (buď klíč verze, anebo celý záznam = instance verze).
		/// Tento objekt bude následně předáván ve všech requestech na čtení / plánování / ukládání dat, takže datový zdroj pozná, s jako verzí se pracuje.
		/// Pokud bude uvedeno více položek se shodným Textem, budou prezentovány jako jedna (ta první). 
		/// Uživatel si vybírá verzi výhradně na základě textu.
		/// </summary>
		public List<StringTag> QueryResultDataVersionList { get; set; }
		/// <summary>
		/// Výsledek requestu QueryDataVersion: aktuálně platná verze, bude přednastavena do toolbaru. Identifikována je textem.
		/// </summary>
		public StringTag QueryResultDataVersionCurrent { get; set; }
		#endregion
	}
	#endregion
	#region CLASS DataSourceRequestQuery : požadavek na získání informací o budoucím requestu
	/// <summary>
	/// DataSourceRequestQuery : požadavek na získání informací o budoucím requestu
	/// </summary>
	public class DataSourceRequestQuery : DataSourceRequest
	{
		#region KONSTRUKCE
		/// <summary>
		/// Protected konstruktor. Objekt má být vytvořen statickým konstruktorem.
		/// </summary>
		/// <param name="graphID">ID grafu, který požadavek vydal</param>
		/// <param name="graphDeclaration">Deklarace grafu, který požadavek vydal. Vstupuje do Requestu a nese informace do datového zdroje.</param>
		/// <param name="requestType">Typ požadavku</param>
		/// <param name="priority">Priorita požadavku</param>
		protected DataSourceRequestQuery(int graphID, GraphDeclarationItemCls graphDeclaration, DataSourceRequestType requestType, int priority) :
			base(graphID, graphDeclaration, requestType, priority)
		{ }
		/// <summary>
		/// Vytvoří a vrátí request pro předání dotazu do datového zdroje.
		/// Dotazem se tento request ptá datového zdroje na jeho názor na případný následující request.
		/// Konkrétně: čeká nás request na plánovací proces. Nejprve se přeptám datového zdroje, zda jej chce odmítnout, případně jak dlouho mu to bude trvat a jak se bude akce jmenovat.
		/// </summary>
		/// <param name="graphID">ID grafu, který se ptá</param>
		/// <param name="graphDeclaration">Deklarace grafu, který požadavek vydal. Vstupuje do Requestu a nese informace do datového zdroje.</param>
		/// <param name="requestType">Druh budoucího requestu, na který se ptáme</param>
		/// <param name="requestData">Data do budoucího requestu (jakákoli identifikace, pochází vždy z daného datového zdroje)</param>
		public static DataSourceRequestQuery CreateQueryAboutRequest(int graphID, GraphDeclarationItemCls graphDeclaration, DataSourceRequestType requestType, IComparable requestData)
		{
			DataSourceRequestQuery request = new DataSourceRequestQuery(graphID, graphDeclaration, DataSourceRequestType.QueryAboutRequest, 5);
			request.QueryRequestType = requestType;         // Na tento požadavek se ptáme v tomto QueryAboutRequest
			request.QueryRequestData = requestData;         // Přidaná data
            request.QueryResultRunTimeout = 300;            // Implicitní timeout
			return request;
		}
		#endregion
		#region PROPERTY
		/// <summary>
		/// { get; } Dotaz na budoucí požadavek: zde se uvádí, na který budoucí požadavek se ptáme
		/// </summary>
		public DataSourceRequestType QueryRequestType { get; protected set; }
		/// <summary>
		/// { get; } Dotaz na budoucí požadavek: zde se uvádí, jaká doplňující data k požadavku patří.
		/// Typicky obsahuje identifikaci datové akce (SAVE, PREPARE, LOAD, PLAN, ...)
		/// </summary>
		public IComparable QueryRequestData { get; protected set; }
		/// <summary>
		/// { get; set; } Dotaz na budoucí požadavek: odpověď, zda datový zdroj odmítá provést tento požadavek.
		/// Nastavením na true dojde ke stornování požadavku.
		/// </summary>
		public bool QueryResultRefuseRequest { get; set; }
		/// <summary>
		/// { get; set; } Dotaz na budoucí požadavek: odpověď, které jiné requesty je třeba spustit před provedením tohoto dotazovaného requestu.
		/// Například: před provedením requestu ActivateData je třeba provést request SaveData.
		/// Vizuální vrstva o tom běžně nemá ponětí, ale datová vrstva ví, jestli má data předešlé verze změněná, a jestli je chce uložit.
		/// </summary>
		public List<IComparable> QueryResultPreRequestList { get; set; }
		/// <summary>
		/// { get; set; } Dotaz na budoucí požadavek: odpověď, které jiné requesty je třeba spustit po provedením tohoto dotazovaného requestu.
		/// Například: po provedením requestu ActivateData je třeba provést request PrepareData a LoadData.
		/// Vizuální vrstva o tom běžně nemá ponětí, ale datová vrstva ví, že data požadované verze plánu ještě nemá načtená a po aktivaci verze je musí načíst.
		/// </summary>
		public List<IComparable> QueryResultPostRequestList { get; set; }
		/// <summary>
		/// { get; set; } Dotaz na budoucí požadavek: odpověď, zda tento požadavek se má vypustit (stejně jej datový zdroj bude ignorovat).
		/// Výchozí hodnota = false, nepřeskakovat.
		/// Nastavení na true jen ušetří režii se spouštěním procesu.
		/// </summary>
		public bool QueryResultSkipThisProcess { get; set; }
		/// <summary>
		/// { get; set; } Dotaz na budoucí požadavek: odpověď, zda tento v průběhu tohoto požadavku bude datový zdroj řídit svůj vlastní progress.
		/// Vlastní progress se volá metodou request.CallProgress().
		/// Pokud bude zde uvedeno true, pak řízení progresu pro jednotlivý process je v režii tohoto procesu (zpracování požadavku v datovém zdroji).
		/// Datový zdroj pak volá progres prostřednictvím metodou request.CallProgress() s nastavením hodnoty float progressRatio.
		/// Pokud zde bude false, pak se progress daného procesu zobrazí jako průběžně probíhající ukazatel (styl: ).
		/// Výchozí hodnota = false, nebude řízen progres.
		/// </summary>
		public bool QueryResultActivateProgress { get; set; }
		/// <summary>
		/// { get; set; } Dotaz na budoucí požadavek: odpověď, jak dlouho relativně bude práce na tomto požadavku trvat.
		/// Výchozí hodnota = 0. Značí, že pro tento proces nebude rezervován žádný úsek ukazatele.
		/// Standardní hodnota = 1. Značí, že pro proces bude rezervována rovnocenná poměrná část ukazatele, jako pro ostatní procesy.
		/// Procesy, které jsou rychlejší, mají nastavit přiměřeně menší hodnotu.
		/// Procesy, které jsou pomalejší, mají nastavit vyšší hodnotu, tím si alokují větší poměrnou část ukazatele.
		/// </summary>
		public double QueryResultRelativeTime { get; set; }
        /// <summary>
        /// { get; set; } Dotaz na budoucí požadavek: odpověď, jak dlouhý timeout v sekundách pro tento požadavek chceme nastavit.
        /// Výchozí hodnota = 300 = 5 minut !
        /// Funkce může timeout nastavit podle očekávané potřeby.
        /// Pokud výkon funkce neskončí v daném čase, dojde k výjimce a výko threadu bude přerušen.
        /// </summary>
        public int QueryResultRunTimeout { get; set; }
        /// <summary>
		/// { get; set; } Dotaz na budoucí požadavek: odpověď, jaký text má být zobrazen pro tento proces.
		/// Výchozí hodnota = null, použije se defaultní název (název datového zdroje: název požadavku).
		/// </summary>
		public string QueryResultProcessName { get; set; }
		#endregion
	}
	#endregion
	#region CLASS DataSourceRequestDataFunction : požadavek spuštění datové funkce (aktivace verze, načtení/uložení dat, další funkce)
	/// <summary>
	/// DataSourceRequestDataFunction : požadavek spuštění datové funkce (aktivace verze, načtení/uložení dat, další funkce)
	/// </summary>
	public class DataSourceRequestDataFunction : DataSourceRequest
	{
		#region KONSTRUKCE
		/// <summary>
		/// Protected konstruktor. Objekt má být vytvořen statickým konstruktorem.
		/// </summary>
		/// <param name="graphID">ID grafu, který požadavek vydal</param>
		/// <param name="graphDeclaration">Deklarace grafu, který požadavek vydal. Vstupuje do Requestu a nese informace do datového zdroje.</param>
		/// <param name="requestType">Typ požadavku</param>
		/// <param name="priority">Priorita požadavku</param>
		protected DataSourceRequestDataFunction(int graphID, GraphDeclarationItemCls graphDeclaration, DataSourceRequestType requestType, int priority) :
			base(graphID, graphDeclaration, requestType, priority)
		{
			this.ResultCorrect = true;
		}
		/// <summary>
		/// Vytvoří a vrátí request pro řízení datového zdroje - předává požadavek na rozsáhlejší akci
		/// </summary>
		/// <param name="graphID">ID grafu, který požadavek vydal</param>
		/// <param name="graphDeclaration">Deklarace grafu, který požadavek vydal. Vstupuje do Requestu a nese informace do datového zdroje.</param>
		/// <param name="requestType">Typ požadavku</param>
		/// <returns>Request, který zajistí načítání těchto dat</returns>
		public static DataSourceRequestDataFunction CreateDataSourceRequest(int graphID, GraphDeclarationItemCls graphDeclaration, DataSourceRequestType requestType)
		{
			DataSourceRequestDataFunction request = new DataSourceRequestDataFunction(graphID, graphDeclaration, requestType, 5);
			return request;
		}
		/// <summary>
		/// Vytvoří a vrátí request pro řízení datového zdroje - předává požadavek na rozsáhlejší akci
		/// </summary>
		/// <param name="graphID">ID grafu, který požadavek vydal</param>
		/// <param name="graphDeclaration">Deklarace grafu, který požadavek vydal. Vstupuje do Requestu a nese informace do datového zdroje.</param>
		/// <param name="requestType">Typ požadavku</param>
		/// <param name="progressMethod">Callback metoda pro zobrazování postupu (ukazatel, progress bar)</param>
		/// <returns>Request, který zajistí načítání těchto dat</returns>
		public static DataSourceRequestDataFunction CreateDataSourceRequest(int graphID, GraphDeclarationItemCls graphDeclaration, DataSourceRequestType requestType, CallbackTargetDelegate progressMethod)
		{
			DataSourceRequestDataFunction request = new DataSourceRequestDataFunction(graphID, graphDeclaration, requestType, 5);
			request.ProgressMethod = progressMethod;
			return request;
		}
		/// <summary>
		/// Vytvoří a vrátí request pro řízení datového zdroje - předává požadavek na rozsáhlejší akci
		/// </summary>
		/// <param name="graphID">ID grafu, který požadavek vydal</param>
		/// <param name="graphDeclaration">Deklarace grafu, který požadavek vydal. Vstupuje do Requestu a nese informace do datového zdroje.</param>
		/// <param name="runRequestData">Data specifikující funkci, předávají se do request.ProgressMethod</param>
		/// <returns>Request, který zajistí načítání těchto dat</returns>
		public static DataSourceRequestDataFunction CreateDataSourceRequest(int graphID, GraphDeclarationItemCls graphDeclaration, DataSourceRequestType requestType, IComparable runRequestData)
		{
			DataSourceRequestDataFunction request = new DataSourceRequestDataFunction(graphID, graphDeclaration, requestType, 5);
			request.RunRequestData = runRequestData;
			return request;
		}
		/// <summary>
		/// Vytvoří a vrátí request pro řízení datového zdroje - předává požadavek na rozsáhlejší akci
		/// </summary>
		/// <param name="graphID">ID grafu, který požadavek vydal</param>
		/// <param name="graphDeclaration">Deklarace grafu, který požadavek vydal. Vstupuje do Requestu a nese informace do datového zdroje.</param>
		/// <param name="progressMethod">Callback metoda pro zobrazování postupu (ukazatel, progress bar)</param>
		/// <param name="runRequestData">Data specifikující funkci, předávají se do request.ProgressMethod</param>
		/// <returns>Request, který zajistí načítání těchto dat</returns>
		public static DataSourceRequestDataFunction CreateDataSourceRequest(int graphID, GraphDeclarationItemCls graphDeclaration, DataSourceRequestType requestType, IComparable runRequestData, CallbackTargetDelegate progressMethod)
		{
			DataSourceRequestDataFunction request = new DataSourceRequestDataFunction(graphID, graphDeclaration, requestType, 5);
			request.ProgressMethod = progressMethod;
			request.RunRequestData = runRequestData;
			return request;
		}
		#endregion
		#region PROPERTY
		/// <summary>
		/// { get; } Identifikace datové akce, v případě že požadovaná akce je typu DataSourceRequestType.RunDataFunction.
		/// Pokud je požadovaná akce jiná než DataSourceRequestType.RunDataFunction, pak je zde null.
		/// Typicky obsahuje identifikaci datové akce (SAVE, PREPARE, LOAD, PLAN, ...), 
		/// a to ve formě kterou si určil datový zdroj sám v odpovědi na nedávno položený požadavek QueryAboutRequest, 
		/// v property DataSourceRequestQuery.QueryResultPreRequestList a DataSourceRequestQuery.QueryResultPostRequestList
		/// </summary>
		public IComparable RunRequestData { get; protected set; }
		/// <summary> { get; set; }
		/// Výsledek: tento datový zdroj s tímto příkazem neměl problém. true = z jeho pohledu je vše v pořádku.
		/// Pokud někdo nastaví false, měl by v dialogovém okně zobrazit důvod problému, jinak to bude dost silent.
		/// </summary>
		public bool ResultCorrect { get; set; }
		/// <summary>
		/// Příznak, že důsledkem editace došlo ke změnám v seznamu linkovaných elementů.
		/// Poté by měla vizuální vrstva znovu načíst seznam linků elementů (požadavkem typu DataSourceRequestReadRelations.CreateLinkNet())
		/// a zobrazovat jej z tohoto nově získaného seznamu.
		/// </summary>
		public bool ResultElementLinkListChanged { get; set; }
		/// <summary> { get; set; }
		/// Výsledek: po doběhnutí tohoto requestu je třeba přenačíst všechny řádky (a tím samozřejmě elementy) ve všech grafech všech datových zdrojů
		/// </summary>
		public bool ResultNeedReloadAllRows { get; set; }
		#endregion
	}
	#endregion
    #region CLASS DataSourceRequestEventEdit : bázová třída pro požadavky EventBeforeEdit a EventAfterEdit
    /// <summary>
    /// DataSourceRequestEventEdit : bázová třída pro požadavky EventBeforeEdit a EventAfterEdit
    /// </summary>
    public class DataSourceRequestEventEdit : DataSourceRequest
    {
        #region KONSTRUKCE
        /// <summary>
        /// Protected konstruktor. Objekt má být vytvořen statickým konstruktorem.
        /// </summary>
        /// <param name="graphID">ID grafu, který požadavek vydal</param>
        /// <param name="graphDeclaration">Deklarace grafu, který požadavek vydal. Vstupuje do Requestu a nese informace do datového zdroje.</param>
        /// <param name="requestType">Typ požadavku</param>
        /// <param name="priority">Priorita požadavku</param>
        protected DataSourceRequestEventEdit(int graphID, GraphDeclarationItemCls graphDeclaration, DataSourceRequestType requestType, int priority, List<IDataElement> activeElementList, List<IDataElement> editedElementList) :
            base(graphID, graphDeclaration, requestType, priority)
        {
            this.ActiveElementList = activeElementList;
            this.EditedElementList = editedElementList;
        }
        #endregion
        #region PROPERTY
        /// <summary> { get; }
        /// Seznam elementů, kterými se aktivně pohybovalo v grafu.
        /// V tomto seznamu nejsou ty elementy, které byly editovány jako navázané.
        /// </summary>
        public List<IDataElement> ActiveElementList { get; protected set; }
        /// <summary>{ get; }
        /// Seznam elementů, kterými se v grafu pohybovalo návazně na aktivní elementy (ty jsou v ActiveElementList).
        /// Zdejší elementy se sice účastnily editace, ale jejich pohyb nebyl cílem editace - ale jen důsledkem.
        /// Proč jsou zde: datový zdroj by měl zjistit, v jakém stavu tyto elementy budou po akceptaci změn v datovém zdroji.
        /// Je dost možné, že se jim upraví čas, anebo se zcela ztratí.
        /// </summary>
        public List<IDataElement> EditedElementList { get; protected set; }
        #endregion
    }
    #endregion
    #region CLASS DataSourceRequestEventBeforeEdit : požadavek na dotaz do datového zdroje, zda je možno editovat daná data
    /// <summary>
    /// DataSourceRequestEventBeforeEdit : požadavek na dotaz do datového zdroje, zda je možno editovat daná data
    /// </summary>
    public class DataSourceRequestEventBeforeEdit : DataSourceRequestEventEdit
    {
        #region KONSTRUKCE
        /// <summary>
        /// Protected konstruktor. Objekt má být vytvořen statickým konstruktorem.
        /// </summary>
        /// <param name="graphID">ID grafu, který požadavek vydal</param>
        /// <param name="graphDeclaration">Deklarace grafu, který požadavek vydal. Vstupuje do Requestu a nese informace do datového zdroje.</param>
        /// <param name="requestType">Typ požadavku</param>
        /// <param name="priority">Priorita požadavku</param>
        protected DataSourceRequestEventBeforeEdit(int graphID, GraphDeclarationItemCls graphDeclaration, DataSourceRequestType requestType, int priority, List<IDataElement> activeElementList, List<IDataElement> editedElementList) :
            base(graphID, graphDeclaration, requestType, priority, activeElementList, editedElementList)
        {
        }
        /// <summary>
        /// Vytvoří a vrátí request pro zápis interaktivních změn, provedených na grafické vrstvě, do podkladové datové vrstvy.
        /// </summary>
        /// <param name="graphID">ID grafu, který požadavek vydal</param>
        /// <param name="graphDeclaration">Deklarace grafu, který požadavek vydal. Vstupuje do Requestu a nese informace do datového zdroje.</param>
        /// <param name="activeElementList">Soupis elementů, kterými se aktivně fyzicky pohybovalo. Nejde tedy o elementy, které se pohybovaly v závěsu.</param>
        /// <param name="editedElementList">Soupis elementů, kterými se sice pohybovalo, ale které nebyly původcem pohybu ale byly jen zúčastněnými prvky.</param>
        /// <returns></returns>
        public static DataSourceRequestEventBeforeEdit CreateEventBeforeEdit(int graphID, GraphDeclarationItemCls graphDeclaration, List<IDataElement> activeElementList, List<IDataElement> editedElementList)
        {
            DataSourceRequestEventBeforeEdit request = new DataSourceRequestEventBeforeEdit(graphID, graphDeclaration, DataSourceRequestType.EventBeforeEdit, 5, activeElementList, editedElementList);
            request.EditEnabled = true;
            return request;
        }
        #endregion
        #region PROPERTY
        /// <summary>
        /// Příznak, zda editace je povolena.
        /// Výchozí hodnota je true = pokud se k požadavku datový zdroj nijak nevyjádří, pak je editace povolena.
        /// </summary>
        public bool EditEnabled { get; set; }
        /// <summary>
        /// Text, který obsahuje důvod zákazu editace.
        /// Text by měl být naplněn v případě, kdy se nastavuje EditEnabled = false.
        /// </summary>
        public string InfoText { get; set; }
        #endregion
    }
    #endregion
	#region CLASS DataSourceRequestEventAfterEdit : požadavek na ošetření stavu po interaktivní editaci dat
	/// <summary>
	/// DataSourceRequestEventAfterEdit : požadavek na ošetření stavu po interaktivní editaci dat
	/// </summary>
	public class DataSourceRequestEventAfterEdit : DataSourceRequestEventEdit
	{
		#region KONSTRUKCE
		/// <summary>
		/// Protected konstruktor. Objekt má být vytvořen statickým konstruktorem.
		/// </summary>
		/// <param name="graphID">ID grafu, který požadavek vydal</param>
		/// <param name="graphDeclaration">Deklarace grafu, který požadavek vydal. Vstupuje do Requestu a nese informace do datového zdroje.</param>
		/// <param name="requestType">Typ požadavku</param>
		/// <param name="priority">Priorita požadavku</param>
        protected DataSourceRequestEventAfterEdit(int graphID, GraphDeclarationItemCls graphDeclaration, DataSourceRequestType requestType, int priority, List<IDataElement> activeElementList, List<IDataElement> editedElementList) :
            base(graphID, graphDeclaration, requestType, priority, activeElementList, editedElementList)
		{ }
		/// <summary>
		/// Vytvoří a vrátí request pro zápis interaktivních změn, provedených na grafické vrstvě, do podkladové datové vrstvy.
		/// </summary>
		/// <param name="graphID">ID grafu, který požadavek vydal</param>
		/// <param name="graphDeclaration">Deklarace grafu, který požadavek vydal. Vstupuje do Requestu a nese informace do datového zdroje.</param>
		/// <param name="activeElementList">Soupis elementů, kterými se aktivně fyzicky pohybovalo. Nejde tedy o elementy, které se pohybovaly v závěsu.</param>
		/// <param name="editedElementList">Soupis elementů, kterými se sice pohybovalo, ale které nebyly původcem pohybu ale byly jen zúčastněnými prvky.</param>
		/// <returns></returns>
		public static DataSourceRequestEventAfterEdit CreateEventAfterEdit(int graphID, GraphDeclarationItemCls graphDeclaration, List<IDataElement> activeElementList, List<IDataElement> editedElementList)
		{
            DataSourceRequestEventAfterEdit request = new DataSourceRequestEventAfterEdit(graphID, graphDeclaration, DataSourceRequestType.EventAfterEdit, 5, activeElementList, editedElementList);
			return request;
		}
		#endregion
		#region PROPERTY
		/// <summary>
		/// { get; set; } Výsledek: GID řádků, jejichž obsah se v procesu editace změnil.
		/// </summary>
		public List<GID> ResultEditChangedRows
		{
			get
			{
				if (_ResultEditChangedRows == null)
					_ResultEditChangedRows = new List<GID>();
				return _ResultEditChangedRows;
			}
			set { _ResultEditChangedRows = value; }
		}
		private List<GID> _ResultEditChangedRows;
		/// <summary>
		/// { get; set; } Výsledek: seznam pointerů na elementy, které jsou aktivní po editaci (namísto původních aktivních elementů).
		/// Odpovídá soupisu vstupních aktivních elementů, které se editovaly (this.ActiveElementList).
		/// Proces editace může původní elementy odebrat, a na jejich místo vložit nové = nové číslo ID elementu.
		/// Aby grafická vrstva mohla znovu vytvořit mapu vztahů, musí mít možnost najít ty elementy, které původně editovala.
		/// </summary>
		public List<DataPointerStr> ResultEditActiveElementPointers
		{
			get
			{
				if (_ResultEditActiveElementPointers == null)
					_ResultEditActiveElementPointers = new List<DataPointerStr>();
				return _ResultEditActiveElementPointers;
			}
			set { _ResultEditActiveElementPointers = value; }
		}
		private List<DataPointerStr> _ResultEditActiveElementPointers;
		/// <summary>
		/// { get; set; } Výsledek: pointery na elementy, které byly v procesu editace přidány.
		/// </summary>
		public List<DataPointerStr> ResultEditNewElements
		{
			get
			{
				if (_ResultEditNewElements == null)
					_ResultEditNewElements = new List<DataPointerStr>();
				return _ResultEditNewElements;
			}
			set { _ResultEditNewElements = value; }
		}
		private List<DataPointerStr> _ResultEditNewElements;
		/// <summary>
		/// { get; set; } Výsledek: pointery na elementy, které byly v procesu editace změněny (tj. zůstávají, ale mají jiná data).
		/// </summary>
		public List<DataPointerStr> ResultEditChangedElements
		{
			get
			{
				if (_ResultEditChangedElements == null)
					_ResultEditChangedElements = new List<DataPointerStr>();
				return _ResultEditChangedElements;
			}
			set { _ResultEditChangedElements = value; }
		}
		private List<DataPointerStr> _ResultEditChangedElements;
		/// <summary>
		/// { get; set; } Výsledek: pointery na elementy, které byly v procesu editace změněny (tj. zůstávají, ale mají jiná data).
		/// </summary>
		public List<DataPointerStr> ResultEditDeletedElements
		{
			get
			{
				if (_ResultEditDeletedElements == null)
					_ResultEditDeletedElements = new List<DataPointerStr>();
				return _ResultEditDeletedElements;
			}
			set { _ResultEditDeletedElements = value; }
		}
		private List<DataPointerStr> _ResultEditDeletedElements;
		/// <summary>
		/// Příznak, že důsledkem editace došlo ke změnám v seznamu linkovaných elementů.
		/// Poté by měla vizuální vrstva znovu načíst seznam linků elementů (požadavkem typu DataSourceRequestReadRelations.CreateLinkNet())
		/// a zobrazovat jej z tohoto nově získaného seznamu.
		/// </summary>
		public bool ResultElementLinkListChanged { get; set; }
		#endregion
	}
	#endregion
    #region CLASS DataSourceCall : třída pro izolované volání datového zdroje, metody RunRequestSync, pro vyřízení požadavků s definovaným TimeOutem
    /// <summary>
    /// DataSourceCall : třída pro izolované volání datového zdroje, metody RunRequestSync, pro vyřízení požadavků s definovaným TimeOutem
    /// </summary>
    public class DataSourceCall : IDisposable
    {
        /// <summary>
        /// Metoda zavolá daný datový zdroj, jeho metodu RunRequestSync() a předá do ní daný request.
        /// Na rozdíl od přímého volání metody datového zdroje zde dojde k volání v izolovaném threadu s nastaveným TimeOutem, 
        /// a v případě potřeby (TimeOut) k jeho abortu.
        /// </summary>
        /// <param name="dataSource"></param>
        /// <param name="request"></param>
        public static void RunRequestSync(IDataSource dataSource, DataSourceRequest request)
        {
            RunRequestSync(dataSource, request, 60000);
        }
        /// <summary>
        /// Metoda zavolá daný datový zdroj, jeho metodu RunRequestSync() a předá do ní daný request.
        /// Na rozdíl od přímého volání metody datového zdroje zde dojde k volání v izolovaném threadu s nastaveným TimeOutem, 
        /// a v případě potřeby (TimeOut) k jeho abortu.
        /// </summary>
        /// <param name="dataSource"></param>
        /// <param name="request"></param>
        public static void RunRequestSync(IDataSource dataSource, DataSourceRequest request, int timeOutMilisec)
        {
            // namísto jednoduchého:
            //   dataSource.RunRequestSync(request);
            // provedu následující:
            using (DataSourceCall dsCall = new DataSourceCall(dataSource, request))
            {
                dsCall.Start();
                bool success = false;
                bool isDebug = Steward.DebugMode;                               // Tady bych mohl v Debug režimu změnit hodnotu isDebug = false, abych otestoval chování TimeOut => Abort i v Debug režimu.
                int timeOut = (timeOutMilisec < 1000 ? 1000 : timeOutMilisec);  // Timeout nechť je minimálně 1 sekunda !!!
                if (!isDebug)
                    // V ostrém režimu čekám jen daný timeout:
                    success = dsCall.Signal.WaitOne(timeOutMilisec);
                else
                    // V debug režimu mohu klidně hodinu debugovat, a přitom nemám v úmyslu nic abortovat:
                    success = dsCall.Signal.WaitOne();
                if (!success)
                {
                    dsCall.Abort();
                    Steward.Audit(AuditRowType.CoreError, "Abort process RunRequestSync() in Datasource " + dataSource.GetType().Name + "; Request: " + request.GetType().Name + ":" + request.RequestType.ToString() + " (Timeout reached)");
                }
            }
        }
        #region Instanční vrstva: jedna instance = jedno volání datového zdroje
        private DataSourceCall(IDataSource dataSource, DataSourceRequest request)
        {
            this._DataSource = dataSource;
            this._Request = request;
            this._Signal = new System.Threading.AutoResetEvent(false);
            this._Thread = new System.Threading.Thread(this._EntryPoint);
            this._Thread.IsBackground = true;
            this._Thread.Name = "IDataSource.RunRequestSync";
        }
        void IDisposable.Dispose()
        {
            this._DataSource = null;
            this._Request = null;
            this._Signal = null;
            this._Thread = null;
        }
        private IDataSource _DataSource;
        private DataSourceRequest _Request;
        private System.Threading.AutoResetEvent _Signal;
        private System.Threading.Thread _Thread;
        /// <summary>
        /// Signální objekt
        /// </summary>
        protected System.Threading.AutoResetEvent Signal { get { return this._Signal; } }
        /// <summary>
        /// Zahájí běh výkonné metody v odděleném vlákně, řízení se ihned vrací zpět.
        /// Před tím je resetován Signal.
        /// Signal bude aktivován po dokončení výkonné metody.
        /// Volající metoda může (ve svém Threadu) po vrácení řízení z této metody počkat na aktivaci signálu (metodou Signal.WaitOne()),
        /// přičemž může specifikovat i timeout (Signal.WaitOne(milisec)).
        /// Pokud WaitOne() vrátí true, značí to že výkonná metoda doběhla.
        /// Pokud WaitOne() vrátí false, značí to že uplynul TimeOut, ale výkonná metoda nedoběhla. Pak je možno vyvolat zdejší metodu Abort().
        /// </summary>
        protected void Start()
        {
            if (this._Thread == null)
                Throw.SysError(MessageInfo.Get("Byla spuštěna metoda DataSourceCall.Start() poté, kdy předchozí metoda skončila."));
            this._Signal.Reset();
            this._Thread.Start();
        }
        /// <summary>
        /// Ukončí běh threadu výkonného vlákna.
        /// Ve vlákně v jeho metodě dojde k výjimce System.Threading.ThreadAbortException.
        /// </summary>
        protected void Abort()
        {
            System.Threading.Thread thread = this._Thread;
            if (thread == null) return;
            thread.Abort("TIMEOUT");
        }
        /// <summary>
        /// Výkonná metoda v odděleném threadu
        /// </summary>
        private void _EntryPoint()
        {
            this._DataSource.RunRequestSync(this._Request);
            this._Thread = null;
            this._Signal.Set();                                 // Pošleme čekající metodě signál, že výkonné vlákno skončilo.
        }
        #endregion
    }
    #endregion
    #region ENUM
    /// <summary>
	/// Typy požadavků na datový zdroj
	/// </summary>
	public enum DataSourceRequestType
	{
		/// <summary>
		/// Žádný požadavek
		/// </summary>
		None = 1,
		/// <summary>
		/// Vizuální vrstva se ptá datové vrstvy, jaké verze dat v aktuální databázi má k dispozici.
		/// Datová vrstva to zjistí (typicky jde o verze plánu) a seznam dostupných verzí uloží do request.QueryResultDataVersionList
		/// </summary>
		QueryDataVersion,
		/// <summary>
		/// Aktivovat verzi dat. Verze je uvedena v requestu.
		/// Plánovací tabule před vydáním tohoto requestu vyžádá z datového zdroje soupis rozšiřujících požadavků na Pre a Post funkce,
		/// a to requestem typu QueryAboutRequest.
		/// Datový zdroj podle svého druhu a aktuálního stavu dat může vložit požadavky další funkce (například uložit data, načíst data, atd).
		/// Tyto vyžádané operace jsou spouštěny v požadovaném pořadí, pomocí requestů RunDataFunction.
		/// </summary>
		ActivateDataVersion,
		/// <summary>
		/// Zeptáme se datového zdroje na nějaký jiný request, který plánujeme v dalším kroku zavolat.
		/// Datový zdroj nastaví odpovědi do request.QueryResult.
		/// </summary>
		QueryAboutRequest,
		/// <summary>
		/// Provede akci s celými daty aktuální verze.
		/// Akce je konkrétně specifikovaná v requestu v property QueryRequestData.
		/// </summary>
		RunDataFunction,
		/// <summary>
		/// Načtení TopLevel seznamu
		/// </summary>
		TopLevelRead,
		/// <summary>
		/// Načtení podřízených řádků
		/// </summary>
		SubRowsRead,
		/// <summary>
		/// Načtení elementů
		/// </summary>
		ElementsRead,
		/// <summary>
		/// Načtení elementů, explicitně adresovaných v request.RequestElementsMap
		/// </summary>
		ElementsMapRead,
		/// <summary>
		/// Vytvořit síť vztahů pro daný GID.
		/// Vstupní GID je uložen v requestu v RequestedGId, typ grafu je v RequestedGraphMode.
		/// </summary>
		CreateDataRelationNet,
		/// <summary>
		/// Vytvořit síť linků mezi elementy (stabilní vztahy) pro daný řádek / pro všechny řádky.
		/// Vstupní GID je uložen v requestu v RequestedGId, typ grafu je v RequestedGraphMode.
		/// </summary>
		CreateDataLinkNet,
		/// <summary>
		/// Najít cílová data v mezigrafové aktivitě.
		/// Zdrojem je element na pointeru this.SourceElement, v grafu typu this.SourceGraphMode.
		/// Heldají se elementy pro graf typu this.RequestedGraphMode, jehož klíčový GID je 
		/// Odpovědi se umísťují do this.TargetElementList.
		/// </summary>
		FindInterGraphTargetData,
        /// <summary>
        /// Událost proběhne před zahájením interaktivních pohybů v grafu.
        /// Typická reakce je: datový zdroj zjistí, zda v dané situaci (verze dat, dotyčné elementy) je možno provést editaci, a uloží odpovídající hodnotu do requestu.
        /// </summary>
        EventBeforeEdit,
		/// <summary>
		/// Požadavek na posunutí elementů na nový čas a řádek.
		/// Vstupující elementy jsou uloženy v request.ActiveElementList
		/// </summary>
		EventAfterEdit,
		/// <summary>
		/// Ukončit připojení k datům, uložit data, uvolnit data z paměti, zapomenout, vyčistit proměnné.
		/// Datový zdroj si zjistí, zda má nějaká data rozpracovaná, a pokud ano zeptá se uživatele na uložení.
		/// Pokud chce uživatel ukládat data, dá do PreRequest = SourceDataSaveAll.
		/// Pokud nechce změny ukládat, nedá tam nic.
		/// Pokud chce stornovat odpojení, nastaví do requestu 
		/// </summary>
		DisconnectDataProfile,
		/// <summary>
		/// Dotaz, zda je možno pracovat s aktuálně připojeným datovám profilem (zda je databáze OK).
		/// </summary>
		CheckDataProfile
	}
	#endregion
}
